home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / dbg / sun4.md / dbgMain.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  31KB  |  1,214 lines

  1. /* dbgMain.c -
  2.  *
  3.  *     This contains the routines which read and execute commands from kdbx.
  4.  *
  5.  *
  6.  * Copyright 1989 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dbg/sun4.md/dbgMain.c,v 9.16 92/09/29 15:52:37 jhh Exp $ SPRITE (Berkeley)";
  18. #endif not lint
  19.  
  20. #include <sprite.h>
  21. #include <dbg.h>
  22. #include <dbgInt.h>
  23. #include <main.h>
  24. #include <mach.h>
  25. #include <proc.h>
  26. #ifndef FIRST_RUN
  27. #include <vm.h>
  28. #include <vmMach.h>
  29. #endif
  30. #include <machMon.h>
  31. #include <net.h>
  32. #include <netEther.h>
  33. #include <netInet.h>
  34. #include <dev.h>
  35. #include <devVid.h>
  36. #include <stdio.h>
  37. #include <bstring.h>
  38. #include <string.h>
  39.  
  40. /*
  41.  * This violates Sprite coding conventions and should be fixed.
  42.  */
  43.  
  44. extern Address vmStackBaseAddr;
  45. extern Address vmStackEndAddr;
  46. extern Address vmBlockCacheBaseAddr;
  47. extern Address vmBlockCacheEndAddr;
  48. extern int VmMachGetKernelContext();
  49. extern void VmMachSetKernelContext();
  50. extern VmMachPTE VmMachGetPageMap();
  51.  
  52.  
  53.  
  54. Boolean dbg_InDebugger = FALSE;            /* TRUE if we are currently in
  55.                          * the debug command loop. */
  56. Boolean    dbg_BeingDebugged = FALSE;        /* TRUE if are under control
  57.                          * of kdbx or kgdb.*/
  58. Boolean    dbg_UsingNetwork = FALSE;        /* TRUE if the debugger is
  59.                          * using the network interface*/
  60. char    requestBuffer[DBG_MAX_REQUEST_SIZE];    /* Buffer to receive request
  61.                          * into. */
  62. int    requestOffset;                /* Offset in buffer where next
  63.                          * bytes should be read from.*/
  64. char    replyBuffer[DBG_MAX_REPLY_SIZE+2];    /* Buffer to hold reply. */
  65. int    replyOffset = 0;            /* Offset in buffer where next
  66.                          * bytes in reply should go. */
  67. int    curMsgNum;                /* The current message that
  68.                          * is being processed. */
  69. int    dbgMonPC;                /* Place to get the PC from
  70.                          * if trap via the monitor.*/
  71. int    dbgTraceLevel;                /* The debugger tracing
  72.                          * level. */
  73. Boolean    dbg_Rs232Debug = FALSE;            /* TRUE if we are using the
  74.                          * RS@#@ line to debug.  FALSE
  75.                          * if we are using the network.
  76.                          * On the sun4, we have only
  77.                          * used the network.
  78.                          */
  79. Boolean    dbg_SyncedDisks = FALSE;        /* For determining in the
  80.                          * debugger whether the disks
  81.                          * got sync'd or not. */
  82.  
  83. /*
  84.  * Number of times to poll before timing out and resending (about 2 seconds).
  85.  */
  86. #ifdef sun3
  87. int    dbgTimeout = 50000;
  88. #endif
  89. #ifdef sun2
  90. int    dbgTimeout = 15000;
  91. #endif
  92. #ifdef sun4
  93. int    dbgTimeout = 150000;
  94. #endif
  95.  
  96. /*
  97.  * Information about the latest packet received.
  98.  */
  99. Boolean            gotPacket;    
  100. int            dbgPacketLength;
  101. Net_InetAddress        dbgMyIPAddr;
  102. Net_InetAddress        dbgSrcIPAddr;
  103. Net_InetAddress        dbgSrcPort;
  104. Net_EtherHdr        dbgEtherHdr;
  105. Net_ScatterGather    dbgGather;
  106. Net_Interface        *dbgInterPtr = (Net_Interface *) NIL;
  107.  
  108. /*
  109.  * Size of debugging packet header and data.
  110.  */
  111. #define    PACKET_HDR_SIZE (sizeof(Net_EtherHdr) + Dbg_PacketHdrSize() + 4 + 2)
  112. #define PACKET_DATA_SIZE (DBG_MAX_REPLY_SIZE - PACKET_HDR_SIZE)
  113.  
  114. /*
  115.  * Strings which describe each of the opcodes that kdbx can send us.
  116.  */
  117. static char *opcodeNames[] = DBG_OPCODE_NAMES ;
  118.  
  119. /*
  120.  * Strings which describe the different exceptions that can occur.
  121. */
  122. static char *exceptionNames[] = DBG_EXECPTION_NAMES ;
  123.  
  124. /*
  125.  * The type of machine that we are on.
  126.  */
  127. int        machineType;
  128.  
  129. /*
  130.  * Whether syslog should remain diverted on continue or not.
  131.  */
  132. static Boolean    syslogDiverted = FALSE;
  133.  
  134. /*
  135.  * Declare global variables.
  136.  */
  137. int        dbgSfcReg;
  138. int        dbgDfcReg;
  139. int         dbgUserContext;
  140. int         dbgKernelContext;
  141. int        dbgTermReason;
  142. int        dbgInDebugger;
  143. int        dbgIntPending;
  144. int        dbgExcType;
  145. Boolean        dbgPanic;
  146. int        dbgSavedSP;
  147. int        dbgMaxStackAddr;
  148. Boolean        dbg_UsingSyslog = FALSE;
  149. Boolean        dbgCanUseSyslog = TRUE;
  150. static       int    oldContext;
  151.  
  152.  
  153. /* 
  154.  * Forward declarations:
  155.  */
  156. static void DbgCheckNmis _ARGS_((void));
  157. static char *    TranslateOpcode _ARGS_((Dbg_Opcode opcode));
  158. static char *    TranslateException _ARGS_((int exception));
  159. static Boolean    ReadRequest _ARGS_((Boolean timeout));
  160. static void    SendReply _ARGS_((void));
  161. static void    GetRequestBytes _ARGS_((int numBytes, Address dest));
  162. static void    PutReplyBytes _ARGS_((int numBytes, Address src));
  163.  
  164.  
  165. /*
  166.  * ----------------------------------------------------------------------------
  167.  *
  168.  * DbgCheckNmis --
  169.  *
  170.  *    Turn Non-maskable-interrupts on and off to allow keyboard events to
  171.  *    take place.  Only needed on Sun-2's because of the funny mapping
  172.  *    between kernel and user address spaces - they are turned on in the
  173.  *    main debugging loop on Sun-3's.
  174.  *
  175.  * Results:
  176.  *     None.
  177.  *
  178.  * Side effects:
  179.  *     None.
  180.  *
  181.  * ----------------------------------------------------------------------------
  182.  */
  183. static void
  184. DbgCheckNmis()
  185. {
  186. #ifdef sun2
  187.     int    oldContext;
  188.     oldContext = VmMachGetKernelContext(); 
  189.     VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  190.     Mach_MonStartNmi();
  191.     Mach_MonStopNmi();
  192.     VmMachSetKernelContext(oldContext);
  193. #endif
  194. }
  195.  
  196.  
  197. /*
  198.  * ----------------------------------------------------------------------------
  199.  *
  200.  * Dbg_InRange --
  201.  *
  202.  *     Return true if the given address is a valid kernel address and false
  203.  *     otherwise.
  204.  *
  205.  * Results:
  206.  *     True if the given address is a valid kernel address and false
  207.  *     otherwise.
  208.  *
  209.  * Side effects:
  210.  *     None.
  211.  *
  212.  * ----------------------------------------------------------------------------
  213.  */
  214. Boolean
  215. Dbg_InRange(addr, numBytes, writeable) 
  216.     unsigned     int addr;     /* Beginning address to check. */
  217.     int        numBytes;     /* Number of bytes to check. */
  218.     Boolean    writeable;    /* TRUE => address must be writeable. */
  219. {
  220. #ifndef FIRST_RUN
  221.     VmMachPTE        pte;
  222. #endif
  223.     int            i;
  224.     unsigned    int    prot;
  225.     int            firstPage;
  226.     int            lastPage;
  227.  
  228.     if (dbgTraceLevel >= 5) {
  229.     printf("Dbg_InRange called with addr 0x%x %d bytes, and writable = %d\n",
  230.         addr, numBytes, (unsigned int) writeable);
  231.     }
  232.     /*
  233.      * Don't look at anything in device space. 
  234.      */
  235.     if (!(((addr + numBytes - 1) < (unsigned int) VMMACH_DEV_START_ADDR) ||
  236.      (addr >= (unsigned int) VMMACH_DMA_START_ADDR))) {
  237.     return FALSE;
  238.     }
  239.     if ((int) (addr) & 0x1) {
  240.     printf("Dbg: odd address: %x\n", addr);
  241.     return(FALSE);
  242.     }
  243. #ifndef FIRST_RUN
  244.     firstPage = ((unsigned int) addr) >> VMMACH_PAGE_SHIFT_INT;
  245.     lastPage = (((unsigned int) addr) + numBytes - 1) >> VMMACH_PAGE_SHIFT_INT;
  246.     for (i = firstPage; i <= lastPage; i++) {
  247.     pte = VmMachGetPageMap((Address)(i << VMMACH_PAGE_SHIFT_INT));
  248.     if (dbgTraceLevel >= 5) {
  249.         printf("pte value was 0x%x\n", pte);
  250.     }
  251.     prot = pte & VMMACH_PROTECTION_FIELD;
  252.     if (!(pte & VMMACH_RESIDENT_BIT)) {
  253.         return(FALSE);
  254.     } else if (writeable) {
  255.         if (prot != VMMACH_KRW_PROT && prot != VMMACH_URW_PROT) {
  256.         return(FALSE);
  257.         }
  258.     } else {
  259.         if (prot != VMMACH_KRW_PROT && prot != VMMACH_URW_PROT &&
  260.         prot != VMMACH_KR_PROT && prot != VMMACH_UR_PROT) {
  261.         return(FALSE);
  262.         }
  263.     }
  264.     }
  265. #endif
  266.  
  267.     return(TRUE);
  268. }
  269.  
  270.  
  271. /*
  272.  * ----------------------------------------------------------------------------
  273.  *
  274.  * TranslateOpcode --
  275.  *
  276.  *     Return the string which describes the given opcode.
  277.  *
  278.  * Results:
  279.  *     The string which describes the given opcode.
  280.  *
  281.  * Side effects:
  282.  *     None.
  283.  *
  284.  * ----------------------------------------------------------------------------
  285.  */
  286. static char *
  287. TranslateOpcode(opcode)
  288.     Dbg_Opcode opcode;        /* The opcode which is to be translated. */
  289. {
  290.     int index;
  291.  
  292.     index = (int) opcode;
  293.     if (index < 0 || index > (int) DBG_UNKNOWN) {
  294.         index = (int) DBG_UNKNOWN;
  295.     }
  296.  
  297.     return(opcodeNames[index]);
  298. }
  299.  
  300.  
  301. /*
  302.  * ----------------------------------------------------------------------------
  303.  *
  304.  * TranslateException --
  305.  *
  306.  *     Return the string that describes the given exception.
  307.  *
  308.  * Results:
  309.  *     None.
  310.  *
  311.  * Side effects:
  312.  *     None.
  313.  *
  314.  * ----------------------------------------------------------------------------
  315.  */
  316. static char *
  317. TranslateException(exception)
  318.     int exception;        /* The exception which is to be translated. */
  319. {
  320.  
  321.     if (exception < 0 || exception > DBG_UNKNOWN_EXCEPT) {
  322.         exception = DBG_UNKNOWN_EXCEPT;
  323.     }
  324.  
  325.     return(exceptionNames[exception]);
  326. }
  327.  
  328.  
  329.  
  330.  
  331. /*
  332.  * ----------------------------------------------------------------------------
  333.  *
  334.  * Dbg_Init --
  335.  *
  336.  *     Initialize the debugger.
  337.  *
  338.  * Results:
  339.  *     None.
  340.  *
  341.  * Side effects:
  342.  *     dbgMonPC and dbgDoTrace are initialized.
  343.  *
  344.  * ----------------------------------------------------------------------------
  345.  */
  346. void
  347. Dbg_Init()
  348. {
  349.     dbgMonPC = 0;
  350.     dbgTraceLevel = 0;
  351.     dbgInDebugger = 0;
  352.     dbgIntPending = 0;
  353.     dbgPanic = FALSE;
  354.     dbg_BeingDebugged = FALSE;
  355.     machineType = Mach_GetMachineType();
  356.     Mach_MonPrintf("Machine type %x\n", machineType);
  357. }
  358.  
  359.  
  360. /*
  361.  * ----------------------------------------------------------------------------
  362.  *
  363.  * Dbg_InputPacket --
  364.  *
  365.  *     See if the current packet is for us.
  366.  *
  367.  * Results:
  368.  *     None.
  369.  *
  370.  * Side effects:
  371.  *     gotPacket is set to true if we got a packet that we liked.
  372.  *
  373.  * ----------------------------------------------------------------------------
  374.  */
  375. void
  376. Dbg_InputPacket(interPtr, packetPtr, packetLength)
  377.     Net_Interface    *interPtr;
  378.     Address        packetPtr;
  379.     int            packetLength;
  380. {
  381.     Address    dataPtr;
  382.     int        dataLength;
  383.     Net_EtherHdr    *etherHdrPtr;
  384.  
  385.     if (interPtr->netType != NET_NETWORK_ETHER) {
  386.     return;
  387.     }
  388.     etherHdrPtr = (Net_EtherHdr *)packetPtr;
  389.     if (etherHdrPtr->type != NET_ETHER_IP) {
  390.     if (dbgTraceLevel >= 5) {
  391.         printf("Non-IP (Type=0x%x) ", (int)etherHdrPtr->type);
  392.     }
  393.     return;
  394.     }
  395.     if (gotPacket) {
  396.     return;
  397.     }
  398.     if (dbgTraceLevel >= 4) {
  399.     printf("Validating packet\n");
  400.     }
  401.     { 
  402.     static char alignedBuffer[NET_ETHER_MAX_BYTES];
  403.         /*
  404.      * Make sure the packet starts on a 32-bit boundry so that we can
  405.      * use structures for describe the data.
  406.      */
  407.     if ( (unsigned int) (packetPtr + sizeof(Net_EtherHdr)) & 0x3 ) {
  408.           bcopy (packetPtr + sizeof(Net_EtherHdr), alignedBuffer,
  409.                 packetLength - sizeof(Net_EtherHdr));
  410.           packetPtr = alignedBuffer;
  411.     } else {
  412.           packetPtr = packetPtr + sizeof(Net_EtherHdr);
  413.     }
  414.  
  415.     if (Dbg_ValidatePacket(packetLength - sizeof(Net_EtherHdr),
  416.                    (Net_IPHeader *)(packetPtr),
  417.                    &dataLength, &dataPtr,
  418.                    &dbgMyIPAddr, &dbgSrcIPAddr, &dbgSrcPort)) {
  419.         if (dbgTraceLevel >= 4) {
  420.         printf("Got a packet: length=%d\n", dataLength);
  421.         }
  422.         bcopy((Address)etherHdrPtr, (Address)&dbgEtherHdr,
  423.             sizeof(Net_EtherHdr));
  424.         gotPacket = TRUE;
  425.         bcopy(dataPtr, requestBuffer, dataLength);
  426.         /*
  427.          * Set the interface we are using. 
  428.          */
  429.         dbgInterPtr = interPtr;
  430.     }
  431.     }
  432. }
  433.  
  434.  
  435. /*
  436.  * ----------------------------------------------------------------------------
  437.  *
  438.  * ReadRequest --
  439.  *
  440.  *     Read the next request from kdbx.
  441.  *
  442.  * Results:
  443.  *     None.
  444.  *
  445.  * Side effects:
  446.  *     TRUE if didn't time out.
  447.  *
  448.  * ----------------------------------------------------------------------------
  449.  */
  450. static Boolean
  451. ReadRequest(timeout)
  452.     Boolean    timeout;    /* TRUE if should timeout after waiting a 
  453.                  * while. */
  454. {
  455.     int    timeOutCounter;
  456.     Net_Interface    *interPtr;
  457.     int        i;
  458.  
  459.     gotPacket = FALSE;
  460.     timeOutCounter = dbgTimeout;
  461.     do {
  462.         DbgCheckNmis();
  463.         /*
  464.          * Listen on all the interfaces. The debugger is relatively
  465.          * stateless so its easiest to just listen on them all.
  466.          */
  467.         for (i = 0; ; i++) {
  468.         interPtr = Net_NextInterface(TRUE, &i);
  469.         if (interPtr == (Net_Interface *) NIL) {
  470.             break;
  471.         }
  472.         Net_RecvPoll(interPtr);
  473.         if (gotPacket) {
  474.             break;
  475.         }
  476.         }
  477.         if (timeout) {
  478.         timeOutCounter--;
  479.         }
  480.     } while(!gotPacket && timeOutCounter != 0);
  481.     if (gotPacket) {
  482.         replyOffset = PACKET_HDR_SIZE;
  483.         requestOffset = 4;
  484.         curMsgNum = *(int *)(requestBuffer);
  485.         if (dbgTraceLevel >= 4) {
  486.         printf("MsgNum = %d\n", curMsgNum);
  487.         }
  488.     }
  489.  
  490.     return(gotPacket);
  491. }
  492.  
  493.  
  494. /*
  495.  * ----------------------------------------------------------------------------
  496.  *
  497.  * GetRequestBytes --
  498.  *
  499.  *     Get the next numBytes bytes from the current request.
  500.  *
  501.  * Results:
  502.  *     None.
  503.  *
  504.  * Side effects:
  505.  *     None.
  506.  *
  507.  * ----------------------------------------------------------------------------
  508.  */
  509. static void
  510. GetRequestBytes(numBytes, dest)
  511.     int        numBytes;
  512.     Address    dest;
  513. {
  514.     bcopy(requestBuffer + requestOffset, dest, numBytes);
  515.     requestOffset += numBytes;
  516. }
  517.  
  518.  
  519. /*
  520.  * ----------------------------------------------------------------------------
  521.  *
  522.  * PutReplyBytes --
  523.  *
  524.  *     Put the given bytes into the reply buffer.
  525.  *
  526.  * Results:
  527.  *     None.
  528.  *
  529.  * Side effects:
  530.  *     None.
  531.  *
  532.  * ----------------------------------------------------------------------------
  533.  */
  534. static void
  535. PutReplyBytes(numBytes, src)
  536.     int        numBytes;
  537.     Address    src;
  538. {
  539.     if (replyOffset + numBytes > DBG_MAX_REPLY_SIZE) {
  540.     printf("PutReplyBytes: Buffer overflow\n");
  541.     numBytes = DBG_MAX_REPLY_SIZE - replyOffset;
  542.     }
  543.     bcopy(src, &replyBuffer[replyOffset], numBytes);
  544.     replyOffset += numBytes;
  545. }
  546.  
  547.  
  548. /*
  549.  * ----------------------------------------------------------------------------
  550.  *
  551.  * SendReply --
  552.  *
  553.  *     Send a reply to kdbx.
  554.  *
  555.  * Results:
  556.  *     None.
  557.  *
  558.  * Side effects:
  559.  *     None.
  560.  *
  561.  * ----------------------------------------------------------------------------
  562.  */
  563. static void
  564. SendReply()
  565. {
  566.     {
  567.     Net_EtherHdr        *etherHdrPtr;
  568.  
  569.     if (dbgTraceLevel >= 4) {
  570.         printf("Sending reply\n");
  571.     }
  572.     etherHdrPtr = (Net_EtherHdr *) (replyBuffer+2);
  573.     etherHdrPtr->source = dbgEtherHdr.destination;
  574.     etherHdrPtr->destination = dbgEtherHdr.source;
  575.     etherHdrPtr->type = dbgEtherHdr.type;
  576.     dbgGather.bufAddr = replyBuffer + sizeof(Net_EtherHdr)+2;
  577.     dbgGather.length = replyOffset - sizeof(Net_EtherHdr)-2;
  578.     dbgGather.mutexPtr = (Sync_Semaphore *) NIL;
  579.     bcopy((char *)&curMsgNum,(char *)(replyBuffer + PACKET_HDR_SIZE - 4),4);
  580.     Dbg_FormatPacket(dbgMyIPAddr, dbgSrcIPAddr, dbgSrcPort,
  581.              replyOffset - sizeof(Net_EtherHdr) - Dbg_PacketHdrSize()-2,
  582.              replyBuffer + sizeof(Net_EtherHdr) + 2);
  583.     Net_RawOutput(dbgInterPtr, (Address) etherHdrPtr, &dbgGather, 1);
  584.     if (dbgTraceLevel >= 4) {
  585.         printf("Sent reply\n");
  586.     }
  587.     }
  588. }
  589.  
  590.  
  591.  
  592. /*
  593.  * ----------------------------------------------------------------------------
  594.  *
  595.  * Dbg_Main --
  596.  *
  597.  *     The main debugger loop.  This will read commands from the network
  598.  *     and call the proper routine to execute them.
  599.  *
  600.  * Results:
  601.  *     None.
  602.  *
  603.  * Side effects:
  604.  *     None.
  605.  *
  606.  * ----------------------------------------------------------------------------
  607.  */
  608. /*ARGSUSED*/
  609. void
  610. Dbg_Main(trapType, trapStatePtr)
  611.     int            trapType;    /* The reason we were called. */
  612.     Mach_RegState    *trapStatePtr;    /* The CPU's state at the trap. */
  613. {
  614.     Boolean          done;        /* Boolean to tell us whether to leave
  615.                      * the main debugger loop */
  616.     Dbg_Opcode          opcode;            /* The operation that was requested */
  617.                     /* Process table entry that we switched
  618.                      * stacks to. */
  619.     Proc_ControlBlock    *procPtr = (Proc_ControlBlock *) NIL;
  620.     Boolean        atInterruptLevel;/* TRUE if we were entered from an
  621.                       * interrupt handler. */
  622.     static int         curContext;
  623.  
  624. #ifdef sun3
  625.     /*
  626.      * Turn on non-maskable interrupts.
  627.      */
  628.     Mach_MonStartNmi();
  629. #endif
  630. #ifndef FIRST_RUN
  631.     /*
  632.      * Switch to kernel context so that we can access the monitor.
  633.      */
  634.     curContext = oldContext = VmMachGetKernelContext();
  635.     VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  636. #endif
  637. #ifdef NOTDEF
  638. /*
  639.  * This is the code the other machine types execute to sync the disks
  640.  * when going into the debugger.  But it seems to cause us to pop out of the
  641.  * debugger, since it context switches to the backend write process.
  642.  * Why does it work (does it?) on the other machines?
  643.  */
  644.     if (!dbg_BeingDebugged) {
  645.     /*
  646.      * Try to sync the disks if we aren't at interrupt level.  If we
  647.      * are don't bother because we'll just hang waiting for interrupts.
  648.      * Of course I could force interrupts to be enabled but I'm not sure
  649.      * if that's a great idea.
  650.      */
  651.     if (mach_NumDisableIntrsPtr[0] == 0 && !mach_AtInterruptLevel) {
  652.         Mach_EnableIntr();
  653.         Sys_SyncDisks(MACH_CALL_DBG_TRAP);
  654.         dbg_SyncedDisks = TRUE;
  655.         Mach_DisableIntr();
  656.     }
  657.     }
  658. #endif NOTDEF
  659.  
  660.     dbg_InDebugger = TRUE;
  661.     /*
  662.      * Put us at interrupt level so that printf won't accidently enable
  663.      * interrupts.
  664.      */
  665.     atInterruptLevel = mach_AtInterruptLevel;
  666.     mach_AtInterruptLevel = TRUE;
  667.  
  668.     /*
  669.      * Force system log output to the console.
  670.      */
  671.     if (!syslogDiverted) {
  672.     Dev_SyslogDebug(TRUE);
  673.     }
  674.  
  675.     if (dbgPanic && DBG_CVT_MACH_TRAP(trapType) == DBG_BREAKPOINT_TRAP ) { 
  676.     dbgPanic = FALSE;
  677.     trapType = DBG_INTERRUPT;
  678.     /*
  679.      * Set the pc to the instruction after the trap.
  680.      */
  681.     trapStatePtr->pc = trapStatePtr->nextPc;
  682.     trapStatePtr->nextPc = trapStatePtr->nextPc+4;
  683.     } 
  684.     /*
  685.      * We want to inform the user what caused the problem.  However we only
  686.      * tell him if: 1) we are debugging the debugger; 2) we are not under 
  687.      * debugger control (i.e. we don't want to inform the user on every trace 
  688.      * trap), 3) we got something besides a trace trap or a breakpoint trap
  689.      * exception.
  690.      */
  691.     if (dbgTraceLevel >= 1 || !dbg_BeingDebugged || 
  692.         (DBG_CVT_MACH_TRAP(trapType) != DBG_BREAKPOINT_TRAP)) { 
  693.     Dev_VidEnable(TRUE);    /* unblank the screen */
  694.     printf("Entering debugger with a %s (%d) exception at PC 0x%x\r\n",
  695.            TranslateException(DBG_CVT_MACH_TRAP(trapType)),trapType,
  696.            (unsigned) trapStatePtr->pc);
  697.     }
  698.  
  699.  
  700.     /*
  701.      * Inform the network module that we're in charge now.
  702.      */
  703.     dbg_UsingNetwork = TRUE;
  704.     /*
  705.      * If we are stopped after a continue or single step must write a
  706.      * null byte to the debugger at the other end.  It knows that if it sees
  707.      * a null byte we are stopped at this end.
  708.      */
  709.     if (dbg_BeingDebugged) {
  710.         unsigned        char    ch;
  711.     int    timeout = 5;
  712.         ch = 0;
  713.         PutReplyBytes(1, (Address)&ch);
  714.         SendReply();
  715.         do {
  716.             if (ReadRequest(TRUE)) {
  717.                 GetRequestBytes(4, (Address)&opcode);
  718.         if (opcode != DBG_CONTINUE) {
  719.             break;
  720.         } else {
  721.             PutReplyBytes(4, (Address) &opcode);
  722.             SendReply();
  723.             continue;
  724.         }
  725.             }
  726.             /*
  727.              * We can only timeout if we are using network debugging.
  728.              */
  729.         Net_RawOutput(dbgInterPtr, (Address) replyBuffer, 
  730.             &dbgGather, 1);
  731.             if (dbgTraceLevel >= 5) {
  732.                 printf("DBG: Timeout\n");
  733.             }
  734.             printf("TI ");
  735.         } while (timeout-- > 0);
  736.     } else {
  737.          short    t_opcode;
  738.      /*
  739.       * The kmsg program still sends short opcodes. If the top 16 bits
  740.       * are zero we assume that it is a long opcode.
  741.       */
  742.         (void) ReadRequest(FALSE);
  743.         GetRequestBytes(2, (Address)&t_opcode);
  744.     if (t_opcode == 0) {
  745.         GetRequestBytes(2, (Address)&t_opcode);
  746.     }
  747.     opcode = (Dbg_Opcode) t_opcode;
  748.  
  749.     }
  750.  
  751.     /*
  752.      * Now read commands until kdbx tells us that we can return.
  753.      */
  754.     done = FALSE;
  755.     while (!done) {
  756.     if (dbgTraceLevel >= 2) {
  757.         printf("Request: %s ", TranslateOpcode(opcode));
  758.     }
  759.  
  760.     /*
  761.      * Process the request 
  762.      */
  763.     switch (opcode) {
  764.  
  765.         /*
  766.          * The client wants to read some data from us ...
  767.          */
  768.  
  769.         case DBG_GET_STOP_INFO: {
  770.         StopInfo    stopInfo;
  771.         stopInfo.codeStart = (int)mach_CodeStart;
  772.         if (procPtr != (Proc_ControlBlock *) NIL &&
  773.             procPtr->machStatePtr != (Mach_State *)NIL) {
  774.             stopInfo.regs = *(procPtr->machStatePtr->switchRegs);
  775.             stopInfo.regs.tbr = trapStatePtr->tbr;
  776.             stopInfo.regs.y = trapStatePtr->y;
  777. #ifndef lint
  778.             stopInfo.regs.pc = ((int) Mach_ContextSwitch)+16;
  779. #endif
  780.             stopInfo.regs.nextPc = stopInfo.regs.pc+4;
  781.  
  782.         } else {
  783.             stopInfo.regs = *trapStatePtr;
  784.         }
  785.         stopInfo.trapType = trapType;
  786.         PutReplyBytes(sizeof(stopInfo), (Address)&stopInfo);
  787.         SendReply();
  788.         break;
  789.         }
  790.         case DBG_READ_ALL_REGS: 
  791.  
  792.         if (procPtr != (Proc_ControlBlock *) NIL &&
  793.             procPtr->machStatePtr != (Mach_State *)NIL) {
  794.             Mach_RegState    regState;
  795.             regState = *(procPtr->machStatePtr->switchRegs);
  796.             regState.tbr = trapStatePtr->tbr;
  797.             regState.y = trapStatePtr->y;
  798.             regState.pc = ((int) &Mach_ContextSwitch)+16;
  799.             regState.nextPc = regState.pc+4;
  800.             PutReplyBytes(sizeof(regState), (Address) ®State);
  801.         } else {
  802.             PutReplyBytes(sizeof(*trapStatePtr),
  803.                      (Address) trapStatePtr);
  804.         }
  805.         SendReply();
  806.         break;
  807.  
  808.         case DBG_GET_DUMP_BOUNDS: {
  809.         Dbg_DumpBounds bounds;
  810.         extern unsigned int end;
  811.         bounds.pageSize = vm_PageSize;
  812.         bounds.stackSize = mach_KernStackSize;
  813.         bounds.kernelCodeStart = (unsigned int) mach_KernStart;
  814.         bounds.kernelCodeSize  = 
  815.             (unsigned int) (((Address)(&end)) - mach_KernStart);
  816.         bounds.kernelDataStart    = ((unsigned int)(&end));
  817.         bounds.kernelDataSize    = (unsigned int) 
  818.                 (vmMemEnd - ((Address)(&end)));
  819.         bounds.kernelStacksStart = (unsigned int)vmStackBaseAddr;
  820.         bounds.kernelStacksSize = (unsigned int) 
  821.                 (vmStackEndAddr - vmStackBaseAddr);
  822.         bounds.fileCacheStart    = (unsigned int)vmBlockCacheBaseAddr;
  823.         bounds.fileCacheSize    = (unsigned int) (vmBlockCacheEndAddr - 
  824.                         vmBlockCacheBaseAddr);
  825.  
  826.         PutReplyBytes(sizeof(bounds), (char *)&bounds);
  827.         SendReply();
  828.         break;
  829.         }
  830.  
  831.         case DBG_GET_VERSION_STRING: {
  832.         char    *version;
  833.  
  834.         version = SpriteVersion();
  835.         PutReplyBytes(strlen(version) + 1, version);
  836.         SendReply();
  837.         break;
  838.         }
  839.         
  840.         case DBG_INST_READ:
  841.         case DBG_DATA_READ: {
  842.         Dbg_ReadMem    readMem;
  843.         int        status;
  844.  
  845.         GetRequestBytes(sizeof(readMem), (Address) &readMem); 
  846.         if (dbgTraceLevel >= 2) {
  847.             printf("Addr=%x Numbytes=%d ",
  848.                 readMem.address, readMem.numBytes);
  849.         }
  850. #ifndef FIRST_RUN
  851.         VmMachSetKernelContext(curContext);
  852. #endif
  853.         if (Dbg_InRange((unsigned int) readMem.address, readMem.numBytes,
  854.                 FALSE)) {
  855.             status = 1;
  856.             PutReplyBytes(sizeof(status), (Address)&status);
  857.             PutReplyBytes(readMem.numBytes, (Address)readMem.address);
  858.         } else {
  859.             if (dbgTraceLevel >= 2) {
  860.             printf("FAILURE ");
  861.             }
  862.             status = 0;
  863.             PutReplyBytes(sizeof(status), (Address)&status);
  864.         }
  865. #ifndef FIRST_RUN
  866.         VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  867. #endif
  868.         SendReply();
  869.         break;
  870.         }
  871.  
  872.         /*
  873.          * The client wants to write something to us.
  874.          */
  875.         case DBG_SET_PID: {
  876.         Proc_PID    pid;
  877.  
  878.         GetRequestBytes(sizeof(pid), (Address) &pid);
  879.          {
  880.             int    dummy;
  881.  
  882.             PutReplyBytes(4, (Address) &dummy);
  883.             SendReply();
  884.         }
  885.         if (dbgTraceLevel >= 2) {
  886.             printf("pid %x ", pid);
  887.         }
  888.         if (pid == 0) {
  889.             procPtr = (Proc_ControlBlock *) NIL;
  890.             curContext = oldContext;
  891.         } else {
  892.             procPtr = Proc_GetPCB(pid);
  893.             if (procPtr == (Proc_ControlBlock *) NIL ||
  894.                 procPtr == (Proc_ControlBlock *) 0 ||
  895.             procPtr->state == PROC_UNUSED ||
  896.                 procPtr->state == PROC_DEAD ||
  897.             procPtr->state == PROC_NEW) {
  898.             printf("Can't backtrace stack for process %x\n",
  899.                     pid);
  900.             procPtr = (Proc_ControlBlock *) NIL;
  901.             } else {
  902.             curContext = VmMach_GetContext(procPtr);
  903.             if (curContext == -1) {
  904.                 printf("No user context loaded for pid 0x%x\n", 
  905.                    pid);
  906.                 curContext = VMMACH_KERN_CONTEXT;
  907.             }
  908.             }
  909.         }
  910.         break;
  911.         }
  912.         case DBG_REBOOT: {
  913.         int    stringLength;
  914.         char    rebootString[100];
  915.         /*
  916.          * For a reboot command first read the size of the string and
  917.          * then the string itself.
  918.          */
  919.         GetRequestBytes(sizeof(int), (Address)&stringLength);
  920.         if (stringLength != 0) {
  921.             GetRequestBytes(stringLength, (Address)rebootString);
  922.         }
  923.         rebootString[stringLength] = '\0';
  924.          {
  925.             int    dummy;
  926.  
  927.             PutReplyBytes(4, (Address) &dummy);
  928.             SendReply();
  929.         }
  930.         Mach_MonReboot(rebootString);
  931.         }
  932.         case DBG_INST_WRITE:
  933.         case DBG_DATA_WRITE: {
  934.         Dbg_WriteMem        writeMem;
  935.         unsigned    char    ch;
  936.         /*
  937.          * For an instruction or a data write we first have to find out 
  938.          * which address to write to and how many bytes to write.  Next
  939.          * we have to make sure that the address is valid.  If it is
  940.          * then we read the data and write it to the given address.  If
  941.          * not we just report an error to kdbx.
  942.          */
  943.         GetRequestBytes(2 * sizeof(int), (Address) &writeMem);
  944.         if (dbgTraceLevel >= 2) {
  945.             printf("Addr=%x Numbytes=%d ",
  946.                 writeMem.address, writeMem.numBytes);
  947.         }
  948.  
  949. #ifndef FIRST_RUN
  950.         VmMachSetKernelContext(curContext);
  951. #endif    
  952.         if (Dbg_InRange((unsigned int) writeMem.address,
  953.                 writeMem.numBytes, opcode == DBG_DATA_WRITE)) {
  954. #ifndef FIRST_RUN
  955.             if (opcode == DBG_INST_WRITE) {
  956.             VmMach_SetProtForDbg(TRUE, writeMem.numBytes, 
  957.                          (Address)writeMem.address);
  958.             }
  959. #endif
  960.             GetRequestBytes(writeMem.numBytes,
  961.                     (Address) writeMem.address);
  962. #ifndef FIRST_RUN
  963.             if (opcode == DBG_INST_WRITE) {
  964.             VmMach_SetProtForDbg(FALSE, writeMem.numBytes, 
  965.                          (Address)writeMem.address);
  966.             }
  967. #endif
  968.             ch = 1;
  969.         } else {
  970.             char    buf[100];
  971.  
  972.             if (dbgTraceLevel >= 2) {
  973.             printf("FAILURE ");
  974.             }
  975.             GetRequestBytes(writeMem.numBytes, buf);
  976.             ch = 0;
  977.         }
  978. #ifndef FIRST_RUN
  979.         VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  980. #endif
  981.  
  982.         PutReplyBytes(1, (char *) &ch);
  983.         SendReply();
  984.  
  985.         break;
  986.         }
  987.  
  988.         case DBG_WRITE_REG: {                
  989.         Dbg_WriteReg    writeReg;
  990.  
  991.         /*
  992.          * First find out which register is being written and
  993.          * then read the value.
  994.          */
  995.         GetRequestBytes(sizeof(writeReg), (Address)&writeReg);
  996.          {
  997.             int    dummy;
  998.  
  999.             PutReplyBytes(4, (Address) &dummy);
  1000.             SendReply();
  1001.         }
  1002.         if (dbgTraceLevel >= 2) {
  1003.             printf("register %d data %x ", writeReg.regNum, 
  1004.                 writeReg.regVal);
  1005.         }
  1006.         ((int *) trapStatePtr)[(writeReg.regNum)] = writeReg.regVal;
  1007.         break;
  1008.         }
  1009.  
  1010.         case DBG_DIVERT_SYSLOG: 
  1011.         GetRequestBytes(sizeof(Boolean), (Address)&syslogDiverted);
  1012.          {
  1013.             int    dummy;
  1014.  
  1015.             PutReplyBytes(4, (Address) &dummy);
  1016.             SendReply();
  1017.         }
  1018.         break;
  1019.  
  1020.         case DBG_BEGIN_CALL: {
  1021.         /*
  1022.          * We are beginning a call command.  Fix up the stack
  1023.          * so that we will be able to continue.  We will put
  1024.          * it back when we are done.
  1025.          */
  1026.         int    dummy;
  1027.         if (dbgCanUseSyslog) {
  1028.             dbg_UsingSyslog = TRUE;
  1029.         }
  1030.  
  1031.         PutReplyBytes(4, (Address) &dummy);
  1032.         SendReply();
  1033.  
  1034.         break;
  1035.         }
  1036.         case DBG_END_CALL: {
  1037.         char    *buffer;
  1038.         int    *firstIndexPtr;
  1039.         int    *lastIndexPtr;
  1040.         int    bufSize;
  1041.         int    length;
  1042.         /*
  1043.          * Dump the syslog buffer.
  1044.          */
  1045.         Dev_SyslogReturnBuffer(&buffer, &firstIndexPtr,
  1046.                        &lastIndexPtr, &bufSize);
  1047. /* #ifdef GOOD_SYSLOG */
  1048.         if (*firstIndexPtr == -1) {
  1049.             length = 0;
  1050.             PutReplyBytes(4, (Address) &length);
  1051.             dbg_UsingSyslog = FALSE;
  1052.         } else if (*firstIndexPtr <= *lastIndexPtr) {
  1053.             length = *lastIndexPtr - *firstIndexPtr + 1;
  1054.             if (length + 4 > PACKET_DATA_SIZE) {
  1055.             length = PACKET_DATA_SIZE - 4;
  1056.             }
  1057.             PutReplyBytes(4, (Address) &length);
  1058.             PutReplyBytes(length,
  1059.                   (Address)&buffer[*firstIndexPtr]);
  1060.             *firstIndexPtr += length;
  1061.             if (*firstIndexPtr > *lastIndexPtr) {
  1062.             *firstIndexPtr = *lastIndexPtr = -1;
  1063.             }
  1064.         } else {
  1065.             length = bufSize - *firstIndexPtr;
  1066.             if (length + 4 > PACKET_DATA_SIZE) {
  1067.             length = PACKET_DATA_SIZE - 4;
  1068.             }
  1069.             PutReplyBytes(4, (Address) &length);
  1070.             PutReplyBytes(length,
  1071.                   (Address)buffer[*firstIndexPtr]);
  1072.             *firstIndexPtr += length;
  1073.             if (*firstIndexPtr == bufSize) {
  1074.             *firstIndexPtr = 0;
  1075.             }
  1076.         }
  1077. #ifdef notdef
  1078.         length = 0;
  1079.         PutReplyBytes(4, (Address) &length);
  1080.         dbg_UsingSyslog = FALSE;
  1081. #endif
  1082.         SendReply();
  1083.         break;
  1084.         }
  1085.         case DBG_CALL_FUNCTION: {
  1086.         Dbg_CallFunc        callFunc;
  1087.         int            returnVal;
  1088.         static int        argBuf[128];
  1089.         GetRequestBytes(2 * sizeof(int), (Address) &callFunc);
  1090.         if (dbgTraceLevel >= 2) {
  1091.             printf("Addr=%x Numbytes=%d ",
  1092.                 callFunc.address, callFunc.numBytes);
  1093.         }
  1094.         VmMachSetKernelContext(curContext);
  1095.         if ((callFunc.numBytes >= 0 && callFunc.numBytes < 128) &&
  1096.              Dbg_InRange((unsigned int) callFunc.address,4,FALSE)) {
  1097.             GetRequestBytes(callFunc.numBytes,(Address) argBuf);
  1098.             returnVal = (* ((int (*)()) callFunc.address))(argBuf[0],
  1099.             argBuf[1],argBuf[2],argBuf[3],argBuf[4],argBuf[5],argBuf[6],
  1100.             argBuf[7],argBuf[8],argBuf[9]);
  1101.         } else {
  1102.  
  1103.             if (dbgTraceLevel >= 2) {
  1104.             printf("FAILURE ");
  1105.             }
  1106.             GetRequestBytes(callFunc.numBytes,(Address)argBuf);
  1107.             returnVal = -1;
  1108.         }
  1109.         VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  1110.         PutReplyBytes(4, (char *) &returnVal);
  1111.         SendReply();
  1112.  
  1113.         break;
  1114.         }
  1115.         case DBG_CONTINUE: {
  1116.         /*
  1117.          * The client wants to continue execution.
  1118.          */
  1119.         int    foo;
  1120.         GetRequestBytes(sizeof(int), 
  1121.                 (Address) &foo);
  1122.         if (dbgTraceLevel >= 2) {
  1123.             printf("Continuing from pc %x ",
  1124.                 trapStatePtr->pc);
  1125.         }
  1126.         {
  1127.             int    dummy;
  1128.  
  1129.             PutReplyBytes(4, (Address) &dummy);
  1130.             SendReply();
  1131.         }
  1132.  
  1133.         dbg_BeingDebugged = TRUE;
  1134.         done = TRUE;
  1135.         break;
  1136.         }
  1137.         case DBG_SINGLESTEP: {
  1138.         /*
  1139.          * The client wants to single step.
  1140.          */
  1141.         int    dummy;
  1142.         GetRequestBytes(sizeof(int),  (Address) &dummy);
  1143.         printf("Sun4's can't single step\n");
  1144.  
  1145.             PutReplyBytes(4, (Address) &dummy);
  1146.         SendReply();
  1147.  
  1148.         break;
  1149.         }
  1150.         case DBG_DETACH:
  1151.         /*
  1152.          * The debugger has terminated and wants to let us go about our
  1153.          * business.
  1154.          */
  1155.         if (dbgTraceLevel >= 2) {
  1156.             printf("Detaching at pc %x ",
  1157.                 trapStatePtr->pc);
  1158.         }
  1159.             {
  1160.             int    dummy;
  1161.  
  1162.             PutReplyBytes(4, (Address) &dummy);
  1163.             SendReply();
  1164.         }
  1165.  
  1166.         dbg_BeingDebugged = FALSE;
  1167.         done = TRUE;
  1168.         printf("Sprite is now detached from the debugger\r\n");
  1169.         break;
  1170.  
  1171.         case DBG_UNKNOWN:
  1172.         printf("debugger: unrecognized request\n");
  1173.         break;
  1174.     }
  1175.  
  1176.     if (dbgTraceLevel >= 2) {
  1177.         printf("\r\n");
  1178.     }
  1179.     if (!done) {
  1180.          short    t_opcode;
  1181.          /*
  1182.           * The kmsg program still sends short opcodes. If the top 16 bits
  1183.           * are zero we assume that it is a long opcode.
  1184.           */
  1185.         (void) ReadRequest(FALSE);
  1186.         GetRequestBytes(2, (Address)&t_opcode);
  1187.         if (t_opcode == 0) {
  1188.         GetRequestBytes(2, (Address)&t_opcode);
  1189.         }
  1190.         opcode = (Dbg_Opcode) t_opcode;
  1191.     }
  1192.     }
  1193.  
  1194.  
  1195. #ifndef FIRST_RUN
  1196.     VmMachSetKernelContext(oldContext);
  1197. #endif
  1198.     mach_AtInterruptLevel = atInterruptLevel;
  1199.     dbg_UsingNetwork = FALSE;
  1200.  
  1201.     /*
  1202.      * Don't force system log output to the console.
  1203.      */
  1204.     if (!syslogDiverted) {
  1205.     Dev_SyslogDebug(FALSE);
  1206.     }
  1207. #ifdef sun3
  1208.     /*
  1209.      * Turn off non-maskable interrupts.
  1210.      */
  1211.     Mach_MonStopNmi();
  1212. #endif
  1213. }
  1214.